home *** CD-ROM | disk | FTP | other *** search
- unit DrBobUUE;
- interface
- uses
- Windows, SysUtils, Classes;
-
- type
- EUUCode = class(Exception);
-
- TAlgorithm = (filecopy, uuencode, uudecode, xxencode, xxdecode, base64encode, base64decode);
- TUnixCRLF = (CRLF, LF);
-
- TProgressEvent = procedure(Percent: Word) of Object;
-
- TBUUCode = class(TComponent)
- public
- { Public class declarations (override) }
- constructor Create(AOwner: TComponent); override;
-
- private
- { Private field declarations }
- FAbout: ShortString;
- FActive: Boolean;
- FAlgorithm: TAlgorithm;
- FFileMode: Word;
- FHeaders: Boolean;
- FInputFileName: TFileName;
- FOutputFileName: TFileName;
- FOnProgress: TProgressEvent;
- FUnixCRLF: TUnixCRLF;
- { Dummy method to get read-only About property }
- procedure Dummy(Ignore: ShortString);
-
- protected
- { Protected Activate method }
- procedure Activate(GoActive: Boolean);
-
- public
- { Public UUCode interface declaration }
- procedure UUCode;
-
- published
- { Published design declarations }
- property About: ShortString read FAbout write Dummy;
- property Active: Boolean read FActive write Activate;
- property Algorithm: TAlgorithm read FAlgorithm write FAlgorithm;
- property FileMode: Word read FFileMode write FFileMode;
- property Headers: Boolean read FHeaders write FHeaders;
- property InputFile: TFileName read FInputFileName write FInputFileName;
- property OutputFile: TFileName read FOutputFileName write FOutputFileName;
- property UnixCRLF: TUnixCRLF read FUnixCRLF write FUnixCRLF;
-
- published
- { Published Event property }
- property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
- end {TBUUCode};
-
-
- implementation
-
- constructor TBUUCode.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FActive := False;
- FFileMode := 0644;
- FHeaders := True;
- FAbout := 'TBUUCode 4.0 (c) 1998 by Bob Swart (aka Dr.Bob - www.drbob42.com)'
- end {Create};
-
- procedure TBUUCode.Dummy(Ignore: ShortString);
- begin
- end {Dummy};
-
- procedure TBUUCode.Activate(GoActive: Boolean);
- begin
- if GoActive and not FActive then
- begin
- FActive := True;
- { Application.ProcessMessages; { Update Object Inspector }
- UUCode;
- FActive := False
- end
- end {Activate};
-
-
- procedure TBUUCode.UUCode;
- const
- SP = #32;
- CR = #13;
- LF = #10;
- EOF= #27;
- const
- header: Array[Boolean] of ShortString =
- ('begin %.4d %s', { + filename }
- 'begin-base64 %.4d %s'); { + filename }
- footer: ShortString = 'end';
- const
- UU: Array[0..63] of Char = '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_';
- XX: Array[0..63] of Char = '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
- B64: Array[0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
- const
- EUUOutputEmpty = 'OutputFileName is empty';
- EUUInputEmpty = 'InputFileName is empty';
- EUUFileTooBig = 'InputFile is too big';
- type
- TTriplet = Array[0..2] of Byte;
- TKwartet = Array[0..3] of Byte;
- var
- InputBuffer,OutputBuffer: Pointer;
- InputBufSize,OutputBufSize: LongInt;
- Size: Cardinal;
- HeadStr: ShortString;
- f: File;
-
- function FileSize(FileName: ShortString): LongInt;
- var
- SRec: TSearchRec;
- begin
- if FindFirst(FileName,faArchive,SRec) = 0 then
- FileSize := SRec.Size
- else FileSize := 0;
- FindClose(SRec)
- end {FileSize};
-
-
- procedure Encode(Base64, XXCode: Boolean);
- const
- TripletBlock: Array[Boolean] of Word = (15,19);
- var
- I,O: ^Char;
- j,k: LongInt;
- Triplet: ^TTriplet;
- Kwartet: ^TKwartet;
-
- procedure PutChar(Ch: Char);
- begin
- O^ := Ch;
- Inc(O);
- Inc(Size)
- end {PutChar};
-
- procedure Triplet2Kwartet(Const Triplet: TTriplet; var Kwartet: TKwartet);
- var
- i: Integer;
- begin
- Kwartet[0] := (Triplet[0] SHR 2);
- Kwartet[1] := ((Triplet[0] SHL 4) AND $30) +
- ((Triplet[1] SHR 4) AND $0F);
- Kwartet[2] := ((Triplet[1] SHL 2) AND $3C) +
- ((Triplet[2] SHR 6) AND $03);
- Kwartet[3] := (Triplet[2] AND $3F);
- for i:=0 to 3 do
- if Kwartet[i] = 0 then
- Kwartet[i] := $40 + Ord(SP)
- else Inc(Kwartet[i],Ord(SP));
- if Base64 then
- for i:=0 to 3 do
- Kwartet[i] := Ord(B64[(Kwartet[i] - Ord(SP)) mod $40])
- else
- if XXCode then
- for i:=0 to 3 do
- Kwartet[i] := Ord(XX[(Kwartet[i] - Ord(SP)) mod $40])
- end {Triplet2Kwartet};
-
- begin
- Size := 0;
- I := InputBuffer;
- O := OutputBuffer;
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize));
- if FHeaders then
- begin
- HeadStr := Format(header[Base64],
- [FFileMode,ExtractFileName(FInputFileName)]);
- for j:=1 to Length(HeadStr) do PutChar(HeadStr[j]);
- if (FUnixCRLF = CRLF) then PutChar(CR);
- PutChar(LF);
- end;
- j := InputBufSize;
- while j >= (TripletBlock[Base64] * SizeOf(TTriplet)) do
- begin
- if not Base64 then
- if XXCode then
- PutChar(XX[TripletBlock[Base64] * SizeOf(TTriplet)])
- else { uucode }
- PutChar(UU[TripletBlock[Base64] * SizeOf(TTriplet)]);
- for k:=1 to TripletBlock[Base64] do
- begin
- Triplet := Addr(I^);
- Inc(I,SizeOf(TTriplet));
- Kwartet := Addr(O^);
- Inc(O,SizeOf(TKWartet));
- Triplet2Kwartet(Triplet^,Kwartet^);
- Inc(Size,SizeOf(TKwartet));
- Dec(j,SizeOf(TTriplet))
- end;
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize));
- if (FUnixCRLF = CRLF) then PutChar(CR);
- PutChar(LF)
- end;
- if not Base64 then
- if XXCode then
- PutChar(XX[j])
- else { uucode }
- PutChar(UU[j]);
- while j > 0 {SizeOf(TTriplet)} do
- begin
- Triplet := Addr(I^);
- Inc(I,SizeOf(TTriplet));
- Kwartet := Addr(O^);
- Inc(O,SizeOf(TKWartet));
- Triplet2Kwartet(Triplet^,Kwartet^);
- Inc(Size,SizeOf(TKwartet));
- Dec(j,SizeOf(TTriplet));
- if j < 0 then
- begin
- Inc(Size,j); { skip last null characters }
- Inc(O,j)
- end
- end;
- if (FUnixCRLF = CRLF) then PutChar(CR);
- PutChar(LF);
- if FHeaders then
- for j:=1 to Length(footer) do PutChar(footer[j]);
- if (FUnixCRLF = CRLF) then PutChar(CR);
- PutChar(LF);
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize))
- end {Encode};
-
-
- procedure Decode(Base64, XXCode: Boolean);
- const
- headend: Array[Boolean] of LongInt = (6, 13);
- var
- j,k: LongInt;
- I,O,E: ^Char;
- Kwartet: TKwartet;
- Triplet: ^TTriplet;
-
- procedure PutChar(Ch: Char);
- begin
- O^ := Ch;
- Inc(O);
- Inc(Size)
- end {PutChar};
-
- procedure Kwartet2Triplet(Kwartet: TKwartet; var Triplet: TTriplet);
- var
- i: Integer;
- begin
- if Base64 then
- begin
- for i:=0 to 3 do
- begin
- case Chr(Kwartet[i]) of
- 'A'..'Z': Kwartet[i] := 0 + Kwartet[i] - Ord('A') + Ord(SP);
- 'a'..'z': Kwartet[i] := 26+ Kwartet[i] - Ord('a') + Ord(SP);
- '0'..'9': Kwartet[i] := 52+ Kwartet[i] - Ord('0') + Ord(SP);
- '+': Kwartet[i] := 62+ Ord(SP);
- '/': Kwartet[i] := 63+ Ord(SP)
- end
- end
- end
- else
- if XXCode then
- begin
- for i:=0 to 3 do
- begin
- case Chr(Kwartet[i]) of
- '+': Kwartet[i] := 0 + Ord(SP);
- '-': Kwartet[i] := 1 + Ord(SP);
- '0'..'9': Kwartet[i] := 2 + Kwartet[i] - Ord('0') + Ord(SP);
- 'A'..'Z': Kwartet[i] := 12 + Kwartet[i] - Ord('A') + Ord(SP);
- 'a'..'z': Kwartet[i] := 38 + Kwartet[i] - Ord('a') + Ord(SP)
- end
- end
- end;
- Triplet[0] := ((Kwartet[0] - Ord(SP)) SHL 2) +
- (((Kwartet[1] - Ord(SP)) AND $30) SHR 4);
- Triplet[1] := (((Kwartet[1] - Ord(SP)) AND $0F) SHL 4) +
- (((Kwartet[2] - Ord(SP)) AND $3C) SHR 2);
- Triplet[2] := (((Kwartet[2] - Ord(SP)) AND $03) SHL 6) +
- ((Kwartet[3] - Ord(SP)) AND $3F)
- end {Kwartet2Triplet};
-
- begin
- Size := 0;
- I := InputBuffer;
- O := OutputBuffer;
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize));
- j := 1;
- k := 0;
- if FHeaders then
- begin
- repeat
- if (I^ = header[Base64,j]) then
- Inc(j)
- else j := 1;
- Inc(k);
- Inc(I)
- until (j = headend[Base64]) or (k >= InputBufSize);
- repeat
- Inc(I);
- Inc(k);
- until (I^ = ' ') or (k >= InputBufSize);
- FOutputFileName := ExtractFilePath(FInputFileName);
- if Length(FOutputFileName) > 0 then
- if FOutputFileName[Length(FOutputFileName)] <> '\' then
- FOutputFileName := FOutputFileName + '\';
- repeat
- Inc(I);
- Inc(k);
- if not (I^ in ['"',CR,LF]) then
- FOutputFileName := FOutputFileName + I^
- until (I^ = LF) or (k >= InputBufSize); { first line }
- while (I^ in [CR,LF]) and (k < InputBufSize) do
- begin
- Inc(I);
- Inc(k) { pass the end-of-line(s) }
- end;
- end;
- if FOutputFileName = '' then
- raise EUUCode.Create(EUUOutputEmpty)
- else
- repeat
- E := I;
- j := 1;
- while (E^ = footer[j]) and (j <= Length(footer))
- and (k+j <= InputBufSize) do
- begin
- Inc(j);
- Inc(E)
- end;
- if j > Length(footer) then k := InputBufSize { exit }
- else
- begin
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize));
- if not Base64 then { skip first character of each line }
- begin
- Inc(I);
- Inc(k)
- end;
- if not (I^ in [CR,LF]) then
- repeat
- E := I;
- j := 0;
- FillChar(Kwartet,SizeOf(TKwartet),#0);
- repeat
- Kwartet[j] := Ord(E^);
- Inc(j);
- Inc(E)
- until (j = SizeOf(TKwartet)) or (E^ in [CR,LF]);
- Inc(I,j);
- Triplet := Addr(O^);
- Inc(O,SizeOf(TTriplet));
- Kwartet2Triplet(Kwartet,Triplet^);
- Inc(Size,SizeOf(TTriplet)+j-SizeOf(TKwartet));
- Inc(k,SizeOf(TKwartet))
- until (I^ in [CR,LF]) or (k >= InputBufSize);
- while (I^ in [CR,LF]) and (k < InputBufSize) do
- begin
- Inc(I);
- Inc(k)
- end
- end
- until k >= InputBufSize;
- if Assigned(FOnProgress) then
- FOnProgress(trunc((100.0 * Size) / OutputBufSize))
- end {Decode};
-
-
- begin { UUCode }
- if FInputFileName = '' then
- raise EUUCode.Create(EUUInputEmpty);
- if (FAlgorithm in [uuencode,xxencode,base64encode,filecopy]) and
- (FOutputFileName = '') then
- raise EUUCode.Create(EUUOutputEmpty);
- InputBufSize := FileSize(FInputFileName); {!!}
- GetMem(InputBuffer,InputBufSize + SizeOf(TTripLet)); {!!}
- FillChar(InputBuffer^,InputBufSize + SizeOf(TTripLet),#0); {!!}
- try
- OutputBufSize := InputBufSize + SizeOf(TTripLet); {!!}
- if FAlgorithm in [uuencode,xxencode,base64encode] then
- OutputBufSize := OutputBufSize + (OutputBufSize div 3)
- + (OutputBufSize div 15) { length, CR, LF }
- + 32;
- if FAlgorithm <> filecopy then
- begin
- GetMem(OutputBuffer,OutputBufSize);
- FillChar(OutputBuffer^,OutputBufSize,#0)
- end;
- try
- System.Assign(f,FInputFileName);
- Reset(f,1);
- BlockRead(f,InputBuffer^,InputBufSize,Size);
- System.Close(f);
- case FAlgorithm of
- uuencode: Encode(False,False);
- xxencode: Encode(False,True);
- base64encode: Encode(True,False);
- uudecode: Decode(False,False);
- xxdecode: Decode(False,True);
- base64decode: Decode(True,False);
- filecopy: OutputBuffer := InputBuffer
- end;
- System.Assign(f,FOutputFileName);
- Rewrite(f,1);
- BlockWrite(f,OutputBuffer^,Size);
- System.Close(f);
- if Assigned(FOnProgress) then
- FOnProgress(100) { ready }
- finally
- if FAlgorithm <> filecopy then
- FreeMem(OutputBuffer, OutputBufSize)
- end
- finally
- FreeMem(InputBuffer, InputBufSize + SizeOf(TTripLet)) {!!}
- end
- end {UUCode};
- end.
-